package com.nineclock.system.service.impl;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;

import java.util.Date;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.nineclock.common.constant.NcConstant;
import com.nineclock.common.constant.SMSConstant;
import com.nineclock.common.enums.MessageTypeEnum;
import com.nineclock.common.enums.ResponseEnum;
import com.nineclock.common.exception.NcException;
import com.nineclock.common.filter.CurrentUserHolder;
import com.nineclock.common.minIo.MinIOFileStorageService;
import com.nineclock.common.oss.OssClientUtils;
import com.nineclock.common.utils.BeanHelper;
import com.nineclock.system.dto.*;
import com.nineclock.system.im.HxImManager;
import com.nineclock.system.mapper.*;
import com.nineclock.system.message.MessageDTO;
import com.nineclock.system.pojo.*;
import com.nineclock.system.service.SysCompanyService;
import com.nineclock.system.service.SysUserService;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;


@Service
@Transactional
public class SysCompanyServiceImpl implements SysCompanyService {

    @Autowired
    private SysCompanyMapper companyMapper;

    @Autowired
    private OssClientUtils clientUtils;

    @Autowired
    private SysCompanyUserMapper companyUserMapper;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private SysRoleMapper roleMapper;

    @Autowired
    private SysCompanyUserRoleMapper companyUserRoleMapper;

    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private SysUserService userService;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired
    private HxImManager hxImManager;

    @Autowired
    private MinIOFileStorageService minIOService;


    @Override
    public List<SysCompanyDTO> queryUserJoinCompany(Long userId) {
        // 参数校验
        if (userId == null) {
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        List<SysCompany> companyList = companyMapper.queryUserJoinCompany(userId);
        if (CollectionUtils.isEmpty(companyList)) {
            throw new NcException(ResponseEnum.USER_NOT_JOIN_COMPANY);
        }

        // 数据转换，将 List<SysCompany> ---> List<SysCompanyDTO>
        List<SysCompanyDTO> companyDTOList = BeanHelper.copyWithCollection(companyList, SysCompanyDTO.class);
        return companyDTOList;
    }

    @Override
    public SysCompanyDTO queryCompanyInfo() {
        // 获取当前登录用户所属的企业id
        Long companyId = CurrentUserHolder.get().getCompanyId();

        // 根据企业id查询企业信息
        SysCompany company = companyMapper.selectById(companyId);
        if (company == null) {
            throw new NcException(ResponseEnum.COMPANY_NOT_FOUND);
        }

        // 数据转换，将SysCompany --> SysCompanyDTO
        return BeanHelper.copyProperties(company, SysCompanyDTO.class);
    }

    @Override
    public String uploadOSS(MultipartFile file) throws Exception {
        // 参数校验
        if (file == null) {
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        // 校验图片类型
        String contentType = file.getContentType();
        if (!NcConstant.ALLOWED_IMG_TYPES.contains(contentType)) {
            throw new NcException(ResponseEnum.INVALID_FILE_TYPE);
        }

        // 判断文件大小
        if (file.getSize() > NcConstant.maxFileSize) {
            throw new NcException(ResponseEnum.FILE_SIZE_EXCEED_MAX_LIMIT);
        }

        // 调用oss工具类上传文件
//        String fileUrl = clientUtils.uploadFile(file.getOriginalFilename(), file.getInputStream());
        //调用minio
        String fileUrl = minIOService.upload("leadnews",file.getOriginalFilename(), file.getInputStream());
        return fileUrl;
    }

    @Override
    public void updateCompanyInfo(SysCompanyDTO companyDTO) {
        // 参数校验
        if (companyDTO == null) {
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        Long companyId = CurrentUserHolder.get().getCompanyId();

        // 更新企业的基本信息
        SysCompany company = new SysCompany();
        company.setId(companyId);
        company.setName(companyDTO.getName());
        company.setLogo(companyDTO.getLogo());
        companyMapper.updateById(company);

        // 更新员工表中的企业名称
        SysCompanyUser sysCompanyUser = new SysCompanyUser();
        sysCompanyUser.setCompanyName(company.getName());

        LambdaQueryWrapper<SysCompanyUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysCompanyUser::getCompanyId, companyId);
        companyUserMapper.update(sysCompanyUser, wrapper);

    }

    @Override
    public SysCompanyUserDTO getCurrentAdmin() {
        // 获取当前企业id
        Long companyId = CurrentUserHolder.get().getCompanyId();

        // 根据企业id获取当前企业的主管理员
        SysCompanyUser currentAdmin = companyUserMapper.getCurrentAdmin(companyId);

        if (currentAdmin == null) {
            throw new NcException(ResponseEnum.COMPANY_ADMIN_NOT_EXISTS);
        }

        // 数据转换，将 SysCompanyUser --> SysCompanyUserDTO
        return BeanHelper.copyProperties(currentAdmin, SysCompanyUserDTO.class);
    }

    @Override
    public void changeAdmin(String code, Long companyUserId) {

        // 参数校验
        if (StringUtils.isEmpty(code) || companyUserId == null) {
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        // 根据员工id查询员工信息，得到手机号码
        SysCompanyUser companyUser = companyUserMapper.selectById(companyUserId);

        // 取出redis中验证码和传入的验证码，进行比较
        String redisCode = redisTemplate.opsForValue().get(SMSConstant.SMS_CHANGE_MANAGER_KEY_PREFIX + companyUser.getMobile());

        if (StringUtils.isEmpty(redisCode) || !redisCode.equals(code)) {
            throw new NcException(ResponseEnum.INVALID_VERIFY_CODE);
        }

        // 先查询原本的主管理员id
        SysCompanyUserDTO currentAdmin = this.getCurrentAdmin();

        // 查询系统管理员的角色id
        LambdaQueryWrapper<SysRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysRole::getCompanyId, currentAdmin.getCompanyId());
        wrapper.eq(SysRole::getRoleName, NcConstant.ADMIN_ROLE_SYS);
        SysRole sysRole = roleMapper.selectOne(wrapper);


        // 更换管理员
        LambdaQueryWrapper<SysCompanyUserRole> updateWrapper = new LambdaQueryWrapper<>();
        updateWrapper.eq(SysCompanyUserRole::getCompanyUserId, currentAdmin.getId());
        updateWrapper.eq(SysCompanyUserRole::getRoleId, sysRole.getId());


        SysCompanyUserRole sysCompanyUserRole = new SysCompanyUserRole();
        sysCompanyUserRole.setCompanyUserId(companyUserId);

        companyUserRoleMapper.update(sysCompanyUserRole, updateWrapper);


    }

    @Override
    public List<SysCompanyDTO> queryCompanyByName(String keyword) {
        // 参数校验
        if (StringUtils.isEmpty(keyword)) {
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        LambdaQueryWrapper<SysCompany> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(SysCompany::getName, keyword);
        List<SysCompany> sysCompanyList = companyMapper.selectList(wrapper);

        return BeanHelper.copyWithCollection(sysCompanyList, SysCompanyDTO.class);
    }

    @Override
    public void applyJoinCompany(SysApplyJoinCompanyUserDTO applyJoinCompanyUserDTO) {
        // 参数校验
        if (applyJoinCompanyUserDTO == null) {
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        // 更新用户信息
        SysUserDTO sysUserDTO = userService.queryUser(applyJoinCompanyUserDTO.getMobile());

        SysUser sysUser = new SysUser();
        sysUser.setId(sysUserDTO.getId());
        sysUser.setUsername(applyJoinCompanyUserDTO.getUserName());
        sysUser.setMobile(applyJoinCompanyUserDTO.getMobile());
        sysUser.setEmail(applyJoinCompanyUserDTO.getEmail());
        sysUser.setUpdateTime(new Date());
        sysUser.setLastLoginCompanyId(applyJoinCompanyUserDTO.getCompanyId());
        userMapper.updateById(sysUser);


        // 添加企业员工数据
        SysCompanyUser sysCompanyUser = new SysCompanyUser();
        sysCompanyUser.setUserId(sysUser.getId());
        sysCompanyUser.setCompanyId(applyJoinCompanyUserDTO.getCompanyId());
        sysCompanyUser.setCompanyName(applyJoinCompanyUserDTO.getCompanyName());
        sysCompanyUser.setPost(applyJoinCompanyUserDTO.getPost());
        sysCompanyUser.setEmail(applyJoinCompanyUserDTO.getEmail());
        sysCompanyUser.setTimeEntry(new Date());
        sysCompanyUser.setRemark(applyJoinCompanyUserDTO.getApplyReason());
        sysCompanyUser.setEnable((short) 0);
        sysCompanyUser.setCreateTime(new Date());
        sysCompanyUser.setUpdateTime(new Date());
        sysCompanyUser.setMobile(applyJoinCompanyUserDTO.getMobile());
        sysCompanyUser.setUserName(applyJoinCompanyUserDTO.getUserName());
        sysCompanyUser.setImageUrl(applyJoinCompanyUserDTO.getImageUrl());

        companyUserMapper.insert(sysCompanyUser);

        // 推送一条加入企业申请的通知给企业管理员，发送消息到MQ
        // 创建消息内容
        MessageDTO messageDTO = new MessageDTO();

        messageDTO.setMessageType(MessageTypeEnum.COMPANY_APPLY.getType());
        messageDTO.setCompanyId(sysCompanyUser.getCompanyId().toString());
        messageDTO.setTitle(MessageTypeEnum.COMPANY_APPLY.getTitle());
        messageDTO.setContent(sysCompanyUser.getUserName() + " 申请加入企业，请及时审批");

        messageDTO.setUseStatus(0); // 未读
        messageDTO.setAudience(MessageTypeEnum.COMPANY_APPLY.getAudience());

        // 获取当前企业的主管理员
        SysCompanyUser currentAdmin = companyUserMapper.getCurrentAdmin(sysCompanyUser.getCompanyId());

        messageDTO.setTargets(Lists.newArrayList(currentAdmin.getMobile()));  // 消息推送的目标

        messageDTO.setApproveStatue(0); // 未审核
        messageDTO.setApplyUserId(sysUser.getId());  // 申请人的用户id
        messageDTO.setApplyUsername(sysUser.getUsername()); // 申请人的用户名称
        messageDTO.setApproveUserId(currentAdmin.getUserId()); // 审批人用户id
        messageDTO.setApproveUsername(currentAdmin.getUserName());  // 审批人用户名称


        // 参数1-主题:标签
        rocketMQTemplate.convertAndSend("messagePushTopic", JSON.toJSONString(messageDTO));

        // 注册用户到环信
        hxImManager.registerUser2HuanXing(sysUser);
    }

    @Override
    public void allowedJoinCompany(SysAllowedJoinCompanyUserDTO allowedJoinCompanyUserDTO) {
        // 参数校验
        if (allowedJoinCompanyUserDTO == null) {
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        if (allowedJoinCompanyUserDTO.getApproved()) {  // 审核通过

            // 修改员工的状态
            LambdaQueryWrapper<SysCompanyUser> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SysCompanyUser::getCompanyId, CurrentUserHolder.get().getCompanyId());
            wrapper.eq(SysCompanyUser::getUserId, allowedJoinCompanyUserDTO.getApplyUserId());
            SysCompanyUser companyUser = companyUserMapper.selectOne(wrapper);

            // 修改的内容
            companyUser.setEnable((short) 1);
            companyUser.setUpdateTime(new Date());
            companyUserMapper.updateById(companyUser);


            // 发送到MQ的第一条消息
            MessageDTO messageDTO = new MessageDTO();

            messageDTO.setMessageType(MessageTypeEnum.COMPANY_APPLY_PASS.getType());
            messageDTO.setCompanyId(CurrentUserHolder.get().getCompanyId().toString());
            messageDTO.setTitle(MessageTypeEnum.COMPANY_APPLY_PASS.getTitle());
            messageDTO.setContent(companyUser.getUserName() + " 申请加入企业，已通过");

            messageDTO.setUseStatus(0); // 未读
            messageDTO.setAudience(MessageTypeEnum.COMPANY_APPLY_PASS.getAudience());
            messageDTO.setTargets(Lists.newArrayList(companyUser.getMobile()));  // 目标是申请人
            messageDTO.setApproveStatue(1); // 已审核
            messageDTO.setApproveResult("1");  // 审核通过
            messageDTO.setApplyUserId(companyUser.getUserId()); // 申请人的用户id
            messageDTO.setApplyUsername(companyUser.getUserName()); // 申请人用户名
            messageDTO.setApproveUserId(CurrentUserHolder.get().getId()); // 当前登录用户id，即审批人
            messageDTO.setApproveUsername(CurrentUserHolder.get().getUsername()); // 当前登录用户名

            // 参数1-主题:标签
            rocketMQTemplate.convertAndSend("messagePushTopic", JSON.toJSONString(messageDTO));

            // 发送第二条消息，消息内容是消息id
            rocketMQTemplate.convertAndSend("allowedJoinCompanyTopic", allowedJoinCompanyUserDTO.getNotifyMsgId());


        } else {
            // 删除员工信息
            LambdaQueryWrapper<SysCompanyUser> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SysCompanyUser::getCompanyId, CurrentUserHolder.get().getCompanyId());
            wrapper.eq(SysCompanyUser::getUserId, allowedJoinCompanyUserDTO.getApplyUserId());
            companyUserMapper.delete(wrapper);

        }

    }
}
